bitkeeper revision 1.1159.96.3 (415c16a40z3XgMlliaGAnrifiHmpNg)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Thu, 30 Sep 2004 14:22:28 +0000 (14:22 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Thu, 30 Sep 2004 14:22:28 +0000 (14:22 +0000)
Move the configuration step for a restored/received domain so that it
is as early as possible in the domain construction process.
Change domain restore to use xfrd to avoid blocking and double
configuration.

tools/libxc/xc.h
tools/libxc/xc_linux_restore.c
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendMigrate.py
tools/xfrd/xen_domain.c
tools/xfrd/xen_domain.h
tools/xfrd/xfrd.c

index 06ce01df69ffa3f8d96cfb5434deba46de0acbf4..dfc9a9f5d7d89a06eb333afa6fc3fae32b24eb01 100644 (file)
@@ -75,9 +75,10 @@ int xc_shadow_control(int xc_handle,
                       xc_shadow_control_stats_t *stats);
 
 
-#define XCFLAGS_VERBOSE 1
-#define XCFLAGS_LIVE    2
-#define XCFLAGS_DEBUG   4
+#define XCFLAGS_VERBOSE   1
+#define XCFLAGS_LIVE      2
+#define XCFLAGS_DEBUG     4
+#define XCFLAGS_CONFIGURE 8
 
 struct XcIOContext;
 int xc_linux_save(int xc_handle, struct XcIOContext *ioctxt);
index 977a60f841b38f2a5abae7c1a2a397aa3dbbfb04..0988055af34b981b9f77bbb9e01126f9ef7956a4 100644 (file)
@@ -245,6 +245,15 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
     }
     shared_info_frame = op.u.getdomaininfo.shared_info_frame;
 
+    if(ioctxt->flags & XCFLAGS_CONFIGURE)
+    {
+        if(xcio_configure_domain(ioctxt))
+        {
+           xcio_error(ioctxt, "Configuring domain failed"); 
+           goto out;
+        }
+    }
+
     if ( (pm_handle = init_pfn_mapper((domid_t)dom)) == NULL )
         goto out;
 
index ef1a3c2135814a3249099f7ca09d503f8cd78a12..5532d5b98f29c34b5fe7edcd0ff4dc1e7169e5e6 100644 (file)
@@ -211,9 +211,9 @@ class XendDomain:
         @param id:     domain id
         @param notify: send a domain died event if true
         """
-        for info in self.domain_by_name.values():
+        for (k, info) in self.domain_by_name.items():
             if info.id == id:
-                del self.domain_by_name[info.name]
+                del self.domain_by_name[k]
         if id in self.domain_by_id:
             info = self.domain_by_id[id]
             del self.domain_by_id[id]
@@ -408,11 +408,15 @@ class XendDomain:
         @return: deferred
         """
         
-        def cbok(dominfo):
-            self._add_domain(dominfo)
-            return dominfo
-        deferred = XendDomainInfo.vm_restore(src, progress=progress)
-        deferred.addCallback(cbok)
+        if 0:
+            def cbok(dominfo):
+                self._add_domain(dominfo)
+                return dominfo
+            deferred = XendDomainInfo.vm_restore(src, progress=progress)
+            deferred.addCallback(cbok)
+        else:
+            xmigrate = XendMigrate.instance()
+            deferred = xmigrate.restore_begin(src)
         return deferred
     
     def domain_get(self, id):
index 9c235e8700b407d09760a9674adc89a4c7fe00d4..a2bf83389fbaf2437365926c3efd1a28e07a9342 100644 (file)
@@ -295,11 +295,6 @@ class XendMigrateInfo(XfrdInfo):
         eserver.inject('xend.domain.migrate',
                        [ self.dominfo.name, self.dominfo.id,
                          "begin", self.sxpr() ])
-        # Special case for localhost: destroy all devices early.
-        if 0 and self.dst_host in ["localhost", "127.0.0.1"]:
-            self.dominfo.restart_cancel()
-            self.dominfo.cleanup()
-            #self.dominfo.destroy_console()
         xfrd.request(['xfr.migrate',
                       self.src_dom,
                       vmconfig,
@@ -307,6 +302,19 @@ class XendMigrateInfo(XfrdInfo):
                       self.dst_port,
                       self.live ])
         
+    def xfr_vm_suspend(self, xfrd, val):
+        def cbok(val):
+            # Special case for localhost: destroy devices early.
+            if self.dst_host in ["localhost", "127.0.0.1"]:
+                self.dominfo.restart_cancel()
+                self.dominfo.cleanup()
+                self.dominfo.destroy_console()
+            return val
+            
+        d = XfrdInfo.xfr_vm_suspend(self, xfrd, val)
+        d.addCallback(cbok)
+        return d
+    
     def xfr_migrate_ok(self, xfrd, val):
         dom = int(sxp.child0(val))
         self.state = 'ok'
@@ -381,7 +389,35 @@ class XendSaveInfo(XfrdInfo):
                        [ self.dominfo.name, self.dominfo.id,
                          self.state, self.sxpr() ])
     
+class XendRestoreInfo(XfrdInfo):
+    """Representation of a restore in-progress and its interaction with xfrd.
+    """
+
+    def __init__(self, xid, file):
+        XfrdInfo.__init__(self)
+        self.xid = xid
+        self.state = 'begin'
+        self.file = file
+
+    def sxpr(self):
+         sxpr = ['restore',
+                 ['id', self.xid],
+                 ['file', self.file] ]
+         return sxpr
 
+    def request(self, xfrd):
+        print '***request>', self.file
+        log.info('restore BEGIN: ' + str(self.sxpr()))
+        xfrd.request(['xfr.restore', self.file ])
+        
+    def xfr_restore_ok(self, xfrd, val):
+        dom = int(sxp.child0(val))
+        dominfo = self.xd.domain_get(dom)
+        self.state = 'ok'
+        if not self.deferred.called:
+            self.deferred.callback(dominfo)
+
+         
 class XendMigrate:
     """External api for interaction with xfrd for migrate and save.
     Singleton.
@@ -477,6 +513,12 @@ class XendMigrate:
         info = XendSaveInfo(xid, dominfo, file)
         return self.session_begin(info)
 
+    def restore_begin(self, file):
+        xid = self.nextid()
+        info = XendRestoreInfo(xid, file)
+        return self.session_begin(info)
+        
+
 def instance():
     global inst
     try:
index b061a86c4cab5af4901b115d24e72f82a9f3a913..5e535301b4cbf173a5dc29fc14b17811e3a88fde 100644 (file)
@@ -108,7 +108,10 @@ int xen_domain_snd(Conn *xend, IOStream *io,
 /** Receive domain state.
  * Create a new domain and store the received state into it.
  */
-int xen_domain_rcv(IOStream *io, uint32_t *dom, char **vmconfig, int *vmconfig_n){
+int xen_domain_rcv(IOStream *io,
+                   uint32_t *dom,
+                   char **vmconfig, int *vmconfig_n,
+                   int *configured){
     int err = 0;
 #ifdef _XEN_XFR_STUB_
     char buf[1024];
@@ -135,11 +138,13 @@ int xen_domain_rcv(IOStream *io, uint32_t *dom, char **vmconfig, int *vmconfig_n
     ioctxt->info = iostdout;
     ioctxt->err = iostderr;
     ioctxt->configure = domain_configure;
+    ioctxt->flags |= XCFLAGS_CONFIGURE;
 
     err = xc_linux_restore(xcinit(), ioctxt);
     *dom = ioctxt->domain;
     *vmconfig = ioctxt->vmconfig;
     *vmconfig_n = ioctxt->vmconfig_n;
+    *configured = (ioctxt->flags & XCFLAGS_CONFIGURE);
 #endif   
     dprintf("< err=%d\n", err);
     return err;
index 2b59f502ee87435756585071311b58d176e9e27e..2ea66b743e46d77e5bbcc590d6b0ba611d17aa4f 100644 (file)
@@ -11,7 +11,10 @@ extern int xen_domain_snd(Conn *xend, IOStream *io,
                           uint32_t dom,
                           char *vmconfig, int vmconfig_n,
                           int live);
-extern int xen_domain_rcv(IOStream *io, uint32_t *dom, char **vmconfig, int *vmconfig_n);
+extern int xen_domain_rcv(IOStream *io,
+                          uint32_t *dom,
+                          char **vmconfig, int *vmconfig_n,
+                          int *configured);
 
 
 extern int xen_domain_configure(uint32_t dom, char *vmconfig, int vmconfig_n);
index 9c68afddb13f377b0d97227ba58c762bf0d0f37f..e2b6e98fa1406375ab057b1f414d55103739bf3a 100644 (file)
@@ -99,6 +99,8 @@ Sxpr oxfr_hello;     // (xfr.hello <major> <minor>)
 Sxpr oxfr_migrate;   // (xfr.migrate <vmid> <vmconfig> <host> <port> <live>)
 Sxpr oxfr_migrate_ok;// (xfr.migrate.ok <value>)
 Sxpr oxfr_progress;  // (xfr.progress <percent> <rate: kb/s>)
+Sxpr oxfr_restore;   // (xfr.restore <file>)
+Sxpr oxfr_restore_ok;// (xfr.restore.ok <vmid>)
 Sxpr oxfr_save;      // (xfr.save <vmid> <vmconfig> <file>)
 Sxpr oxfr_save_ok;   // (xfr.save.ok)
 Sxpr oxfr_vm_destroy;// (xfr.vm.destroy <vmid>)
@@ -113,6 +115,8 @@ void xfr_init(void){
     oxfr_migrate        = intern("xfr.migrate");
     oxfr_migrate_ok     = intern("xfr.migrate.ok");
     oxfr_progress       = intern("xfr.progress");
+    oxfr_restore        = intern("xfr.restore");
+    oxfr_restore_ok     = intern("xfr.restore.ok");
     oxfr_save           = intern("xfr.save");
     oxfr_save_ok        = intern("xfr.save.ok");
     oxfr_vm_destroy     = intern("xfr.vm.destroy");
@@ -540,6 +544,14 @@ int xfr_send_migrate_ok(Conn *conn, uint32_t vmid){
     return (err < 0 ? err : 0);
 }
 
+int xfr_send_restore_ok(Conn *conn, uint32_t vmid){
+    int err = 0;
+
+    err = IOStream_print(conn->out, "(%s %d)",
+                         atom_name(oxfr_restore_ok), vmid);
+    return (err < 0 ? err : 0);
+}
+
 int xfr_send_save_ok(Conn *conn){
     int err = 0;
 
@@ -777,6 +789,46 @@ int xfr_save(Args *args, XfrState *state, Conn *xend, char *file){
     return err;
 }
 
+/** Restore a vm from file.
+ *
+ * @return 0 on success, error code otherwise
+ */
+int xfr_restore(Args *args, XfrState *state, Conn *xend, char *file){
+    int err = 0;
+    IOStream *io = NULL;
+    int configured=0;
+
+    dprintf("> file=%s\n", file);
+    io = gzip_stream_fopen(file, "rb");
+    if(!io){
+        eprintf("> Failed to open %s\n", file);
+        err = -EINVAL;
+        goto exit;
+    }
+    err = xen_domain_rcv(io,
+                         &state->vmid_new,
+                         &state->vmconfig, &state->vmconfig_n,
+                         &configured);
+    if(err) goto exit;
+    if(!configured){
+        err = xen_domain_configure(state->vmid_new, state->vmconfig, state->vmconfig_n);
+        if(err) goto exit;
+    }
+    err = xen_domain_unpause(state->vmid_new);
+  exit:
+    if(io){
+        IOStream_close(io);
+        IOStream_free(io);
+    }
+    if(err){
+        xfr_error(xend, err);
+    } else {
+        xfr_send_restore_ok(xend, state->vmid_new);
+    }
+    dprintf("< err=%d\n", err);
+    return err;
+}
+
 /** Accept the transfer of a vm from another node.
  *
  * @param peer connection
@@ -787,17 +839,23 @@ int xfr_recv(Args *args, XfrState *state, Conn *peer){
     int err = 0;
     time_t t0 = time(NULL), t1;
     Sxpr sxpr;
+    int configured=0;
 
     dprintf(">\n");
-    err = xen_domain_rcv(peer->in, &state->vmid_new, &state->vmconfig, &state->vmconfig_n);
+    err = xen_domain_rcv(peer->in,
+                         &state->vmid_new,
+                         &state->vmconfig, &state->vmconfig_n,
+                         &configured);
     if(err) goto exit;
     // Read from the peer. This is just so we wait before configuring.
     // When migrating to the same host the peer must destroy the domain
     // before we configure the new one.
     err = Conn_sxpr(peer, &sxpr);
     if(err) goto exit;
-    err = xen_domain_configure(state->vmid_new, state->vmconfig, state->vmconfig_n);
-    if(err) goto exit;
+    if(!configured){
+        err = xen_domain_configure(state->vmid_new, state->vmconfig, state->vmconfig_n);
+        if(err) goto exit;
+    }
     err = xen_domain_unpause(state->vmid_new);
     if(err) goto exit;
     // Report new domain id to peer.
@@ -878,6 +936,17 @@ int xfrd_service(Args *args, int peersock, struct sockaddr_in peer_in){
         if(err) goto exit;
         err = xfr_save(args, state, conn, file);
 
+    } else if(sxpr_elementp(sxpr, oxfr_restore)){
+        // Restore message from xend.
+        char *file;
+        XfrState _state = {}, *state = &_state;
+        int n = 0;
+
+        dprintf("> xfr.restore\n");
+        err = stringof(sxpr_childN(sxpr, n++, ONONE), &file);
+        if(err) goto exit;
+        err = xfr_restore(args, state, conn, file);
+
     } else if(sxpr_elementp(sxpr, oxfr_xfr)){
         // Xfr message from peer xfrd.
         XfrState _state = {}, *state = &_state;